package com.icbc.digitalwallet.service.impl;

import com.icbc.digitalwallet.common.enums.BankCodeEnum;
import com.icbc.digitalwallet.common.enums.ResponseEnum;
import com.icbc.digitalwallet.common.enums.TransTypeEnum;
import com.icbc.digitalwallet.common.exception.Assert;
import com.icbc.digitalwallet.common.exception.BusinessException;
import com.icbc.digitalwallet.common.util.GetYearMonthWeek;
import com.icbc.digitalwallet.common.util.MD5;
import com.icbc.digitalwallet.common.util.TransNoUtils;
import com.icbc.digitalwallet.mapper.DigitalWalletMapper;
import com.icbc.digitalwallet.mapper.TransFlowMapper;
import com.icbc.digitalwallet.pojo.VO.CardInfoAndTransInfo;
import com.icbc.digitalwallet.pojo.VO.DayDetail;
import com.icbc.digitalwallet.pojo.VO.TransVO;
import com.icbc.digitalwallet.pojo.entity.Card;
import com.icbc.digitalwallet.mapper.CardMapper;
import com.icbc.digitalwallet.pojo.entity.DigitalWallet;
import com.icbc.digitalwallet.pojo.entity.TransFlow;
import com.icbc.digitalwallet.service.CardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tx
 * @since 2021-07-17
 */
@Service
public class CardServiceImpl extends ServiceImpl<CardMapper, Card> implements CardService {
    @Autowired
    private DigitalWalletMapper digitalWalletMapper;

    @Autowired
    private TransFlowMapper transFlowMapper;

    @Autowired
    private CardMapper cardMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    /**
     * 获取卡式软钱包的信息以及交易明细
     * 卡式软钱包首页
     * @param id
     * @param type
     * @return
     */
    @Override
    public CardInfoAndTransInfo getCardInfoAndTrans(String id, Integer type) {

        CardInfoAndTransInfo cardInfoAndTrans = new CardInfoAndTransInfo();

        //根据卡式软钱包的id获取卡式软钱包的信息
        Card card = cardMapper.getCardInfo(id);
        Assert.notNull(card, ResponseEnum.CARD_NOT_ACTIVATE);
        cardInfoAndTrans.setCard(card);

        //根据卡式软钱包的id获取卡式软钱包的交易信息
        List<TransFlow> transFlows = transFlowMapper.selectByCardId(id, type);

        //返回剩余充卡次数
        Integer rTimes;
        DayDetail dayTimes = new DayDetail();
        String key = "times-"+ id;
        String times = redisTemplate.opsForValue().get(key);
        if (times == null){
            rTimes = 3;
        }else{
            rTimes = 3 - Integer.parseInt(times);
        }
        dayTimes.setCardTimes(rTimes.toString());
        cardInfoAndTrans.setDayDetail(dayTimes);

        for (TransFlow transFlow : transFlows) {
            transFlow.setTransTypeName(TransTypeEnum.getTransTypeName(transFlow.getTransType()));
            transFlow.setYear(GetYearMonthWeek.getYear(transFlow.getCreateTime()));
            transFlow.setMonth(GetYearMonthWeek.getMonth(transFlow.getCreateTime()));
            transFlow.setWeek(GetYearMonthWeek.getWeek(transFlow.getCreateTime()));
            transFlow.setDays(GetYearMonthWeek.getDay(transFlow.getCreateTime()));
            if(transFlow.getTransTypeName() == "充值"){
                transFlow.setResultAmount("+" + transFlow.getAmount());
            }else{
                transFlow.setResultAmount("-" + transFlow.getAmount());
            }
            transFlow.setAmount(null);
            transFlow.setTransType(null);
            transFlow.setCreateTime(null);
        }
        if (transFlows.size() != 0 ){
            cardInfoAndTrans.setTransFlows(transFlows);
        }

        return cardInfoAndTrans;
    }

    /**
     * 卡式软钱包开立
     * @param id
     */
    @Override
    public void CardEstablish(String id) {
        //查询id是否已经开卡(未完待续)
        Card card = cardMapper.selectById(id);
        Assert.isNull(card, ResponseEnum.CARD_IS_ACTIVATED);
        //若未开卡，将卡数据加入数据库
        Card newCard = new Card();
        newCard.setCId(id);
        newCard.setAmount(new BigDecimal(0));
        cardMapper.insert(newCard);
    }


    @Override
    public void cho(String cId, TransVO transVO) {
        //限制充值次数
        String key = "times-"+cId;
        final int chances = 3;
        Integer times = 0;
//        String expiredTime = null;
        String res = redisTemplate.opsForValue().get(key);

        if (res==null){
//            redisTemplate.opsForValue().set(cId,"0",3, TimeUnit.MINUTES);
            redisTemplate.opsForValue().set(key,"0");
        }else {
            times = Integer.parseInt(res);
            if (times>=chances){
                throw new BusinessException(ResponseEnum.WITHDRAW_CARD_TIMES_ERROR);
            }
        }




//========校验参数========================================================
        //获取输入的支付密码
        String password = transVO.getPayPassword();
        Assert.notEmpty(password,ResponseEnum.TRANS_PAYPASSWORD_EMPTY_ERROR);

        //查询卡式钱包账户
        Card card = baseMapper.selectById(cId);
        if (card==null){
            //throw new BusinessException("请先开立卡式钱包");
            throw new BusinessException(ResponseEnum.CARD_NOT_ACTIVATE);
        }

        //交易金额
        BigDecimal camount = transVO.getAmount();
        if (camount==null || camount.compareTo(new BigDecimal("0")) != 1){
            //throw new BusinessException("充值金额异常");
            throw new BusinessException(ResponseEnum.RECHARGE_AMOUNT_ERROR);

        }

        //交易对象账户的id 此处是数字钱包账号
        String transObjId = transVO.getTransObjId();
        Assert.notEmpty(transObjId,ResponseEnum.TRANS_OBJ_EMPTY_ERROR);

        //根据id查询数字钱包
        DigitalWallet digitalWallet = digitalWalletMapper.selectById(transObjId);
        Assert.notNull(digitalWallet,ResponseEnum.TRANS_OBJ_NULL_ERROR);
        if (camount.compareTo(digitalWallet.getAmount()) == 1){
            //throw new BusinessException("数字钱包余额不足");
            throw new BusinessException(ResponseEnum.ACCOUNT_BANK_BALANCE_ERROR);
        }

        //获取数字钱包的支付密码
        String payPassword = digitalWallet.getPayPassword();
        //验证支付密码 不正确则抛异常
        if (!payPassword.equals(MD5.encrypt(password))){
            //throw new BusinessException("支付密码错误");
            throw new BusinessException(ResponseEnum.PASSWORD_ERROR);
        }
        if (camount.compareTo(new BigDecimal("500"))== 1){
            //throw new BusinessException("充值金额达到上限");
            throw new BusinessException(ResponseEnum.ACCOUNT_UPPER_ERROR);
        }
//========= 转账操作=====================================================================
        //数字钱包余额
        BigDecimal digitalWalletAmount = digitalWallet.getAmount();
        //数字钱包减去交易金额
        digitalWallet.setAmount(digitalWalletAmount.subtract(camount));
        digitalWalletMapper.updateById(digitalWallet);
        //卡式钱包加上充值金额
        BigDecimal cardAmount = card.getAmount();
        BigDecimal max = BigDecimal.valueOf(20000);

        if (max.compareTo(cardAmount.add(camount))== 1){
            card.setAmount(cardAmount.add(camount));
        }
        else{
            //throw new BusinessException("卡式余额已满");
            throw new BusinessException(ResponseEnum.CARD_ACCOUNT_UPPER_ERROR);
        }

        baseMapper.updateById(card);

//============交易流水=====================================================
        //记录用户交易流水
        //设置交易对象
        TransFlow transFlowUser = new TransFlow();
        transFlowUser.setUserId(card.getCId());
        transFlowUser.setTransObj(digitalWallet.getDwId());
        transFlowUser.setTransObjName(digitalWallet.getNickName());
        //设置交易类型 0充值 1提现 2转入 3 转出 在枚举TransTypeEnum中
        transFlowUser.setTransType(TransTypeEnum.RECHARGE.getTransType());
        //交易金额
        transFlowUser.setAmount(camount);
        //交易流水单号
        String transNo = TransNoUtils.getNo();
        transFlowUser.setTransNo(transNo);
        //交易结果
        transFlowUser.setTransResult(true);
        transFlowMapper.insert(transFlowUser);

        //记录交易对象流水
        TransFlow transFlowObj = new TransFlow();
        transFlowObj.setUserId(digitalWallet.getDwId());
        transFlowObj.setTransObj(card.getCId());
        String cid = Integer.parseInt(card.getCId().toString(), 16) + "";
        String cname = "卡式软钱包尾号" + cid.toString().substring(cid.length()-4);
        transFlowObj.setTransObjName(cname);
        transFlowObj.setTransType(TransTypeEnum.TRANS_OUT.getTransType());
        //交易金额
        transFlowObj.setAmount(camount);
        //流水
        transFlowObj.setTransNo(transNo);
        transFlowObj.setTransResult(true);
        transFlowMapper.insert(transFlowObj);

//=====================记录交易次数============================================================

//        if (times+1==chances){
////            redisTemplate.opsForValue().set(cId,"lock",24,TimeUnit.HOURS);
//            redisTemplate.opsForValue().set(key,"lock");
//        }else {
//            redisTemplate.opsForValue().increment(key,1);
//        }
        redisTemplate.opsForValue().increment(key,1);


    }

    @Override
    public void tix(String cId, String tId) {
//============校验参数========================================
        //查询卡式钱包账户
        Card card = baseMapper.selectById(cId);
        if (card==null){
            //throw new BusinessException("请先开立卡式钱包");
            throw new BusinessException(ResponseEnum.CARD_NOT_ACTIVATE);
        }

        //交易金额为卡式钱包全部金额

        BigDecimal amount = card.getAmount();
        if (amount.compareTo(new BigDecimal("0")) != 1){
            throw new BusinessException(ResponseEnum.WITHDRAW_CARD_AMOUNT_ERROR);
        }
        //根据id查询数字钱包
        DigitalWallet digitalWallet = digitalWalletMapper.selectById(tId);
        Assert.notNull(digitalWallet,ResponseEnum.TRANS_OBJ_NULL_ERROR);

//============转账操作================================================
        //数字钱包余额
        BigDecimal digitalWalletAmount = digitalWallet.getAmount();
        //数字钱包加上交易金额
        digitalWallet.setAmount(digitalWalletAmount.add(amount));
        digitalWalletMapper.updateById(digitalWallet);
        //卡式钱包减去提现金
        BigDecimal cardAmount = card.getAmount();
        card.setAmount(cardAmount.subtract(amount));
        baseMapper.updateById(card);

//============业务流水================================================
        //记录用户交易流水
        //设置交易对象名称
        TransFlow transFlowUser = new TransFlow();
        transFlowUser.setUserId(card.getCId());
        transFlowUser.setTransObj(digitalWallet.getDwId());
        transFlowUser.setTransObjName(digitalWallet.getNickName());

        //设置交易类型 0充值 1提现 2转入 3 转出 在枚举TransTypeEnum中
        transFlowUser.setTransType(TransTypeEnum.WITHDRAW.getTransType());
        //交易金额
        transFlowUser.setAmount(amount);
        //交易流水单号
        String transNo = TransNoUtils.getNo();
        transFlowUser.setTransNo(transNo);
        //交易结果
        transFlowUser.setTransResult(true);
        transFlowMapper.insert(transFlowUser);

        //记录交易对象流水
        TransFlow transFlowObj = new TransFlow();
        transFlowObj.setUserId(digitalWallet.getDwId());
        transFlowObj.setTransObj(card.getCId());
        String cid = Integer.parseInt(card.getCId().toString(), 16) + "";
        String cname = "卡式软钱包尾号" + cid.toString().substring(cid.length()-4);
        transFlowObj.setTransObjName(cname);
        transFlowObj.setTransType(TransTypeEnum.TRANS_IN.getTransType());
        //交易金额
        transFlowObj.setAmount(amount);
        //流水
        transFlowObj.setTransNo(transNo);
        transFlowObj.setTransResult(true);
        transFlowMapper.insert(transFlowObj);

    }


}
